﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Licenta1.RayTracer;


namespace Licenta1.Shapes
{
    class Csg : Shape
    {
        MathShape MS1, MS2;
        CSG.Operator op;
        double r, g, b, reflectivity;

        Expression parameters;
        bool init = false;

        public Csg(Context con, Expression expr)
            : base(con)
        {
            parameters = expr;
        }

        private void CheckParameters()
        {
            try
            {
                ParameterList p_list = (ParameterList)parameters;

                MS1 = Set((Shape)p_list.FirstValue);
                p_list = (ParameterList)p_list.SecondValue;
                MS2 = Set((Shape)p_list.FirstValue);
                p_list = (ParameterList)p_list.SecondValue;
                string oper = (string)p_list.FirstValue;

                switch (oper)
                {
                    case "\'difference\'": { op = CSG.Operator.Difference; break; }
                    case "\'union\'": { op = CSG.Operator.Union; break; }
                    case "\'intersection\'": { op = CSG.Operator.Intersection; break; }
                    default: { op = CSG.Operator.Union; break; }
                }

                p_list = (ParameterList)p_list.SecondValue;
                r = (double)p_list.FirstValue;
                p_list = (ParameterList)p_list.SecondValue;
                g = (double)p_list.FirstValue;

                if (p_list.SecondValue is ParameterList)
                {
                    p_list = (ParameterList)p_list.SecondValue;
                    b = (double)p_list.FirstValue;
                    reflectivity = (double)p_list.SecondValue;
                }
                else
                    b = (double)p_list.SecondValue;
            }
            catch (FormatException)
            {
                Console.WriteLine("Error handling parameters to plane.");
            }
        }


        private MathShape Set(Shape MS1)
        {
            if (MS1 is Cube)
            {
                Cube c = ((Cube)MS1);
                return new MathCube(new Vector(c.x, c.y, c.z), c.length);
            }
            if (MS1 is Sphere)
            {
                Sphere s = ((Sphere)MS1);
                return new MathSphere(new Vector(s.x, s.y, s.z), s.radius);
            }
            if (MS1 is Csg)
            {
                Csg s = ((Csg)MS1);
                return new Licenta1.RayTracer.CSG(s.MS1, s.MS2, s.op);
            }

            return null;
        }

        public override string Display()
        {
            if (!init)
                CheckParameters();
            init = true;

            return "{Csg: rgb = (" + r + "; " + g + "; " + b + "); reflectivity = " + reflectivity + " }";
        }

        public override object Value
        {
            get
            {
                if (!init)
                    CheckParameters();
                return this;
            }
        }

        public override void Draw()
        {
            if (MS1 != null && MS2 != null)
            {
                if (!init)
                    CheckParameters();
                if (reflectivity == -1)
                    context.mp.rt.AddObject(new CSG(MS1, MS2, op), new Licenta1.RayTracer.SolidColorMaterial(r, g, b));
                else
                    context.mp.rt.AddObject(new CSG(MS1, MS2, op), new Licenta1.RayTracer.SolidColorMaterial(r, g, b, reflectivity));
            }
        }
    }
}
